`timescale 1ns/1ns
`define DATA_WIDTH 256

module functional(input clk,
				  input rst_n,
				  input curve_sel,//0 256r1
								  //1 sm2
				  input mod,//0 模p
							//1 模n
				  input re_t1,//给T1清零，签名需要
				  input re_t7,//给T7清零，签名需要
				  input [`DATA_WIDTH-1:0] x1,//基点G_x或PA_x
				  input [`DATA_WIDTH-1:0] y1,//基点G_y或PA_y
				  input [`DATA_WIDTH-1:0] k,
				  input [`DATA_WIDTH-1:0] dA,
				  //input [`DATA_WIDTH-1:0] p,
				  //input [`DATA_WIDTH-1:0] n,
				  //input [`DATA_WIDTH-1:0] a,
				  input [`DATA_WIDTH-1:0] Hv_r,
				  input [`DATA_WIDTH-1:0] sm3_e,
				  input [`DATA_WIDTH-1:0] r,//签名求r
				  input [`DATA_WIDTH-1:0] ss,//签名求模n乘
				  input [`DATA_WIDTH-1:0] s,//签名求s
				  input [`DATA_WIDTH-1:0] v_r,
				  input [`DATA_WIDTH-1:0] v_s,//验签输入s
				  input [`DATA_WIDTH-1:0] k1,//验签kg做完后的x
				  input [`DATA_WIDTH-1:0] kg_y,//验签kg做完后的y
				  input MM_enable,
				  input inv_enable,
				  input func,
				  //input modn,//做模n加,选择n,签名需要
				  input [21:0] r_sel,//选择哪个寄存器存哪个值
				  input [7:0] M_sel_a,//选择模乘输入
				  input [7:0] M_sel_b,//选择模乘输入
				  input [7:0] A_sel_a,//选择模加输入
				  input [7:0] A_sel_b,//选择模加输入
				  input [1:0] I_sel,//选择模逆的输入
				  output [`DATA_WIDTH-1:0] t1,
				  output [`DATA_WIDTH-1:0] t2,
				  output [`DATA_WIDTH-1:0] t3,
				  output [`DATA_WIDTH-1:0] t4,
				  output [`DATA_WIDTH-1:0] t5,
				  output [`DATA_WIDTH-1:0] t7,
				  output MM_end_flag,
				  output INV_end_flag
				 );
reg [`DATA_WIDTH-1:0] mul_a,mul_b;				 
wire [`DATA_WIDTH-1:0] mul_c;
reg [`DATA_WIDTH-1:0] add_a,add_b;
wire [`DATA_WIDTH-1:0] add_c;
wire [`DATA_WIDTH-1:0] t0,t6;
reg [`DATA_WIDTH-1:0] inv_a;
wire [`DATA_WIDTH-1:0] inv_c;


always @(*)
begin
	case(M_sel_a)
		8'b00000001 : mul_a = t0;
		8'b00000010 : mul_a = t1;
		8'b00000100 : mul_a = t2;
		8'b00001000 : mul_a = t3;
		8'b00010000 : mul_a = t4;
		8'b00100000 : mul_a = t5;
		8'b01000000 : mul_a = t6;
		8'b10000000 : mul_a = t7;
		default : mul_a = `DATA_WIDTH'd0;
	endcase
end

always @(*)
begin
	case(M_sel_b)
		8'b00000001 : mul_b = t0;
		8'b00000010 : mul_b = t1;
		8'b00000100 : mul_b = t2;
		8'b00001000 : mul_b = t3;
		8'b00010000 : mul_b = t4;
		8'b00100000 : mul_b = t5;
		8'b01000000 : mul_b = t6;
		8'b10000000 : mul_b = t7;
		default : mul_b = `DATA_WIDTH'd0;
	endcase
end

always @(*)
begin
	case(A_sel_a)
		8'b00000001 : add_a = t0;
		8'b00000010 : add_a = t1;
		8'b00000100 : add_a = t2;
		8'b00001000 : add_a = t3;
		8'b00010000 : add_a = t4;
		8'b00100000 : add_a = t5;
		8'b01000000 : add_a = t6;
		8'b10000000 : add_a = t7;
		8'b10000001 : add_a = 256'd1;
		8'b10000010 : add_a = v_r;
		8'b10000100 : add_a = sm3_e;
		default : add_a = `DATA_WIDTH'd0;
	endcase
end

always @(*)
begin
	case(A_sel_b)
		//8'b00000001 : add_b = t0;
		8'b00000010 : add_b = t1;
		8'b00000100 : add_b = t2;
		8'b00001000 : add_b = t3;
		8'b00010000 : add_b = t4;
		8'b00100000 : add_b = t5;
		8'b01000000 : add_b = t6;
		8'b10000000 : add_b = t7;
		8'b10000001 : add_b = dA;
		8'b10000010 : add_b = v_s;
		default : add_b = `DATA_WIDTH'd0;
	endcase
end

always @(*)
begin
	case(I_sel)
		2'b01 : inv_a = t3;
		2'b10 : inv_a = k;
		2'b11 : inv_a = v_s;
		default : inv_a = `DATA_WIDTH'd0;
	endcase
end

ModOp modop(.clk(clk),.rst_n(rst_n),.curve_sel(curve_sel),.mod(mod),/*.p(p),*/.mul_a(mul_a),.mul_b(mul_b),.mul_enable(MM_enable),.add_a(add_a),.add_b(add_b),.func(func),/*.modn(modn),*/.inv_a(inv_a),.inv_enable(inv_enable),.mul_c(mul_c),.mul_end_flag(MM_end_flag),.add_c(add_c),.inv_c(inv_c),.inv_end_flag(INV_end_flag));

Register REG(.clk(clk),.rst_n(rst_n),.curve_sel(curve_sel),.re_t1(re_t1),.re_t7(re_t7),.r_sel(r_sel),.mul_c(mul_c),.add_c(add_c),.inv_c(inv_c),/*.a(a),*/.x1(x1),.y1(y1),.Hv_r(Hv_r),.r(r),.ss(ss),.s(s),.k1(k1),.kg_y(kg_y),.k(k),.MM_end_flag(MM_end_flag),.T0(t0),.T1(t1),.T2(t2),.T3(t3),.T4(t4),.T5(t5),.T6(t6),.T7(t7)); 

endmodule